package uutalk.netcloud.talk.base.mqtt;

import com.apkfuns.logutils.LogUtils;

import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;


import uutalk.netcloud.talk.base.mqtt.callback.EventBusMqttCallback;
import uutalk.netcloud.talk.base.mqtt.callback.SimpleMqttActionListener;
import uutalk.netcloud.talk.base.mqtt.event.MQTTActionEvent;
import uutalk.netcloud.talk.base.mqtt.model.Connection;
import uutalk.netcloud.talk.base.mqtt.model.Publication;
import uutalk.netcloud.talk.base.mqtt.model.Subscription;

/**
 * ClassName: MQTTManager
 * Desc:
 * Created by zhiw on 2017/3/24.
 */

public class MQTTManager {

    private static MQTTManager INSTANCE;
    private MqttAsyncClient mqttAsyncClient;
    private MqttCallback mqttCallback;
    private IMqttActionListener mqttActionListener;
    private Connection connection;
    private boolean hasConnected = false;//是否连接过
    private boolean isConnecting = false;//是否正在连接
    private boolean isSubscribeSuccess = false;
    private int reConnectCount = 0;
    private boolean isDestory = false;


    public boolean isSubscribeSuccess() {
        return isSubscribeSuccess;
    }


    @Subscribe
    public void onEvent(MQTTActionEvent event) {

        LogUtils.e("MQTT状态 %d", event.getStatus());
        isConnecting = false;
        if (event.getStatus() == MqttConstant.MQTTStatusConstant.CONNECT_SUCCESS || event.getStatus() == MqttConstant.MQTTStatusConstant.RECONNNECTION_SUCCESS) {
            hasConnected = true;
            reConnectCount = 0;
            isSubscribeSuccess = false;
            subscribeAccount();
        } else if (event.getStatus() == MqttConstant.MQTTStatusConstant.CONNECT_FAIL) {
            isSubscribeSuccess = false;
        } else if (event.getStatus() == MqttConstant.MQTTStatusConstant.SUBSCRIBE_SUCCESS) {
            isSubscribeSuccess = true;
        } else if (event.getStatus() == MqttConstant.MQTTStatusConstant.SUBSCRIBE_FAIL) {
            isSubscribeSuccess = false;
        } else if (event.getStatus() == MqttConstant.MQTTStatusConstant.CONNECTION_LOST) {
            isSubscribeSuccess = false;
        }
    }

    /**
     * 订阅服务器主题
     */
    public void subscribeAccount() {
        Subscription subscription = SubscribeFactory.createSubscribe(connection.getClientId());
        MQTTManager.getInstance().subscribe(subscription);
    }

    public void subscribeUser(String userId) {
        Subscription subscription = SubscribeFactory.createSubscribe(userId);
        MQTTManager.getInstance().subscribe(subscription);

    }

    public static MQTTManager getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new MQTTManager();
        }
        return INSTANCE;
    }

    private MQTTManager() {
        mqttCallback = new EventBusMqttCallback();
        mqttActionListener = new SimpleMqttActionListener();
        EventBus.getDefault().register(this);
    }

    private Connection createConnect(String clientId) {
        Connection connection = new Connection(MqttConstant.HOST, MqttConstant.PORT, clientId, false);
        connection.setUsername("client");
        connection.setPassword("b436f1c015f511e7a00b005056c00008");
        return connection;
    }

    public boolean isConnecting() {
        return isConnecting;
    }


    public void reConnect() {
        String clientid ;
        if (!isDestory) {
            clientid = connection.getClientId();
        }else{
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {

                while (!isConnected() && !isDestory) {
                    try {
                        connect(clientid);
                        LogUtils.e("自动重连中.......");
                        Thread.sleep(2000 + 1000 * reConnectCount);
                        reConnectCount++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    /**
     * 连接

     */
    public synchronized void connect(String clientId) {

        LogUtils.e("连接mqtt");
        if (isConnected() || isConnecting||clientId==null) {
            return;
        }
        isConnecting = true;
        this.connection = createConnect(clientId);
        if (mqttAsyncClient == null) {
            mqttAsyncClient = createClient(connection.getServerURI(), connection.getClientId());
        }
        MqttConnectOptions options = new MqttConnectOptions();
        options.setPassword(connection.getPassword().toCharArray());
        options.setUserName(connection.getUsername());
        options.setAutomaticReconnect(true);
        options.setCleanSession(connection.isCleanSession());


        mqttAsyncClient.setCallback(mqttCallback);
        try {
            mqttAsyncClient.connect(options, MqttConstant.MQTTUserContextConstant.CONNECT_CONTEXT, mqttActionListener);
        } catch (MqttException e) {
            e.printStackTrace();
        }

    }

    /**
     * 取消订阅
     * @param topic
     * @return
     */
    public boolean unsubscribe(String topic) {
        if (isConnected()) {
            try {
                mqttAsyncClient.unsubscribe(topic, MqttConstant.MQTTUserContextConstant.UNSUBSCRIBE_CONTEXT, mqttActionListener);
                return true;
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 是否已连接
     * @return
     */
    public boolean isConnected() {
        if (mqttAsyncClient != null) {
            boolean isConnect = mqttAsyncClient.isConnected();
            return isConnect;
        }
        return false;
    }

    public boolean isHasConnected() {
        return hasConnected;
    }

    /**
     * 订阅一个主题
     * @param subscription
     */
    public boolean subscribe(Subscription subscription) {
        if (isConnected()) {
            try {
                LogUtils.e("订阅主题");
                LogUtils.e(subscription);
                mqttAsyncClient.subscribe(subscription.getTopic(), subscription.getQoS(), MqttConstant.MQTTUserContextConstant.SUBSCRIBE_CONTEXT, mqttActionListener);
                return true;
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
        return false;
    }


    /**
     * 发布一个主题
     * @param publication
     * @return
     */
    public boolean publish(Publication publication) {
        if (isConnected()) {
            try {
                LogUtils.e("发布主题");
                LogUtils.e(publication);
                mqttAsyncClient.publish(publication.getTopic(), publication.getMessage(), MqttConstant.MQTTUserContextConstant.PUBLISH_CONTEXT, mqttActionListener);
                return true;
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
        return false;
    }


    /**
     * 销毁
     */
    public void destory() {
        try {
            if (INSTANCE != null) {
                disConnect();
                if (mqttAsyncClient != null) {
                    mqttAsyncClient.close();
                }
            }
            System.out.println("销毁成功");
        } catch (Exception e) {
            System.out.println("销毁失败");
            e.printStackTrace();
        } finally {
            isDestory = true;
            mqttAsyncClient = null;
            mqttCallback = null;
            mqttActionListener = null;
            EventBus.getDefault().unregister(this);
            INSTANCE = null;
        }

    }


    /**
     * 取消连接
     * @throws MqttException
     */
    public void disConnect() throws MqttException {
        if (mqttAsyncClient != null && mqttAsyncClient.isConnected()) {
            mqttAsyncClient.disconnect();
        }
    }


    /**
     * 创建一个mqtt客户端
     * @param serverURI
     * @param clientId
     * @return
     */
    private MqttAsyncClient createClient(String serverURI, String clientId) {
        MqttClientPersistence mqttClientPersistence = new MemoryPersistence();
        try {
            MqttAsyncClient client = new MqttAsyncClient(serverURI, clientId, mqttClientPersistence);
            return client;
        } catch (MqttException e) {
            e.printStackTrace();
        }
        return null;

    }


}
